package com.huiyi.quickproj.jundui;


import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.concurrent.CompletableFuture;

public class AsyncReadWriteFileByLine {
    public static void main(String[] args) {
        // 读取的文件路径
        String inputFile = "D:\\project\\ieducation_training\\外部项目\\jundui_csv2sql\\data\\china\\population_data.csv";

        // 写入的文件路径
        String outputFile = "D:\\project\\ieducation_training\\外部项目\\jundui_csv2sql\\data\\china\\population_data.sql";

        try {
            // 异步读取文件内容并立即写入新文件
            CompletableFuture<Void> operation = readAndWriteAsync(inputFile, outputFile);

            // 等待操作完成
            operation.join();

            System.out.println("Async file read and write operation completed.");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static CompletableFuture<Void> readAndWriteAsync(String inputFile, String outputFile) {
        return CompletableFuture.runAsync(() -> {
            try {
                // 打开一个异步文件通道用于读取
                AsynchronousFileChannel readFileChannel = AsynchronousFileChannel.open(
                        Paths.get(inputFile),
                        StandardOpenOption.READ
                );

                // 打开一个异步文件通道用于写入
                AsynchronousFileChannel writeFileChannel = AsynchronousFileChannel.open(
                        Paths.get(outputFile),
                        StandardOpenOption.WRITE,
                        StandardOpenOption.CREATE,
                        StandardOpenOption.TRUNCATE_EXISTING
                );

                // 创建一个ByteBuffer，用于存储读取的数据
                ByteBuffer buffer = ByteBuffer.allocate(1024);

                // 异步读取文件内容并写入新文件
                readAndWriteLoop(readFileChannel, writeFileChannel, buffer);
            } catch (IOException e) {
                throw new RuntimeException("Error reading or writing file", e);
            }
        });
    }

    private static void readAndWriteLoop(AsynchronousFileChannel readFileChannel, AsynchronousFileChannel writeFileChannel, ByteBuffer buffer) {
        // 异步读取文件内容
        readFileChannel.read(buffer, 0, null, new CompletionHandler<Integer, Void>() {
            @Override
            public void completed(Integer bytesRead, Void attachment) {
                try {
                    if (bytesRead > 0) {
                        buffer.flip(); // 切换为读取模式

                        // 处理读取的数据（这里示例为将数据转换为字符串）
                        String content = StandardCharsets.UTF_8.decode(buffer).toString();

                        // 异步写入新文件
                        writeAsync(writeFileChannel, content);

                        // 清空缓冲区，准备下一次读取
                        buffer.clear();

                        // 继续异步读取文件内容
                        readAndWriteLoop(readFileChannel, writeFileChannel, buffer);
                    } else {
                        // 读取完成，关闭通道
                        closeChannels(readFileChannel, writeFileChannel);
                    }
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }

            @Override
            public void failed(Throwable exc, Void attachment) {
                exc.printStackTrace();
                closeChannels(readFileChannel, writeFileChannel);
            }
        });
    }

    private static void writeAsync(AsynchronousFileChannel fileChannel, String content) throws IOException {
        // 将字符串转换为字节数组
        byte[] data = content.getBytes(StandardCharsets.UTF_8);

        // 创建一个ByteBuffer，将数据写入其中
        ByteBuffer buffer = ByteBuffer.wrap(data);

        // 异步写入文件
        fileChannel.write(buffer, fileChannel.size(), null, new CompletionHandler<Integer, Void>() {
            @Override
            public void completed(Integer result, Void attachment) {
                // 写入完成
            }

            @Override
            public void failed(Throwable exc, Void attachment) {
                exc.printStackTrace();
            }
        });
    }

    private static void closeChannels(AsynchronousFileChannel... channels) {
        for (AsynchronousFileChannel channel : channels) {
            try {
                if (channel != null) {
                    channel.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

